package com.ubao.network.resp;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Hashtable;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

import com.ubao.network.HttpConnection;
import com.ubao.network.HttpConstants;
import com.ubao.network.RequestInterface;
import com.ubao.network.ResponseInterface;

public class CommonResponse implements ResponseInterface {
	private Hashtable hash = new Hashtable();

	private static final byte START_FLAG = (byte) '{';

	private static final byte END_FLAG = (byte) '}';

	private static final byte OTHER_FLAG = (byte) ':';

	public CommonResponse() {
	}

	/**
	 * 读取返回信息
	 * 
	 * @return
	 * @throws Exception
	 */
	private byte[] readResponse(HttpURLConnection conn, InputStream inputStream) {
		try {
			byte[] data = null;
			if (conn != null && inputStream != null) {
				int len = (int) conn.getContentLength();
				// 读取模式1：直接获取数据长度

				if (conn.getRequestMethod().equals(HttpConnection.HEAD)) {

					return null;
				}

				if (len <= 0) {
					// 读取模式2：从Http连接头获取数据长度
					String bodyLength = null;
					bodyLength = conn.getHeaderField("content-length");

					if (bodyLength != null) {
						try {
							len = Integer.parseInt(conn
									.getHeaderField("Body-Length"));
						} catch (Exception e) {
							// e.printStackTrace();
						}
					}
				}

				if (len > 0) {
					int actual = 0;
					int bytesread = 0;
					data = new byte[len];
					while ((bytesread != len) && (actual != -1)) {
						actual = inputStream.read(data, bytesread, len
								- bytesread);
						// logger.debug("actual: " + actual);
						if (actual >= 0) {
							bytesread += actual;
						}
					}

					if (bytesread == 0) {
						return null;
					} else if (bytesread < len) {
						byte[] actualData = new byte[bytesread];
						System.arraycopy(data, 0, actualData, 0, bytesread);

						return actualData;
					}
				} else {
					// 读取模式3：持续读取，直到数据包结束
					ByteArrayOutputStream tmp = new ByteArrayOutputStream();
					byte[] buffer = new byte[HttpConstants.BUFFER_SIZE];
					int count;
					while ((count = inputStream.read(buffer, 0,
							HttpConstants.BUFFER_SIZE)) != -1) {
						tmp.write(buffer, 0, count);
					}
					data = tmp.toByteArray();
					tmp.close();
					tmp = null;
					buffer = null;
				}
			}
			return data;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public void setData(HttpURLConnection conn, InputStream inputStream,
			RequestInterface request, boolean isCmwap) throws Exception {
		final byte[] bytes = readResponse(conn, inputStream);
		analysisData(bytes, true);
	}

	/**
	 * 分析数据 解析TYPE和真正数据content
	 * 
	 * @param data
	 *            byte[]
	 */
	public void analysisData(byte[] _data, boolean isStart) {
		StructResponse struct = new StructResponse(_data);
		byte[] data = null;
		try {
			while (isStart) {
				int v = struct.readByte();
				if (v == -1) {
					throw new IOException(" DATA");
				}
				if (v == START_FLAG) {
					break;
				}
			}

			int type = struct.readShort();

			// 包属性 byte[2]
			byte arr1 = (byte) struct.readByte(); // 0 标志位
			struct.readByte(); // 0 标志位
			boolean needDecompress = ((arr1 & 0x02) != 0);

			// type = 5000 表示后面子包外面套了一个大包
			if (type == 5000) {
				// 正文数据,结束符号一并读进来
				data = struct.readByteArrayWithEndFlag();
				if (needDecompress) {
					data = decompress(data);
				}
				this.analysisData(data, true);
				return;
			} else if (type == 6005) {
				data = struct.readByteArrayWithEndFlag();
//				if (needDecompress) {
//					data = decompress(data);
//				}
				this.analysisData(data, true);
				return;
			} else {
				data = struct.readByteArray();
				if (needDecompress) {
					data = decompress(data);
				}
			}

			byte tmp = (byte) struct.readByte();
			if (tmp == END_FLAG)// modified by wyp
			{
				putData(type, data);
			} else if (tmp == OTHER_FLAG) {
				putData(type, data);
				analysisData(struct.getOthers(), false);
			} else if (tmp == START_FLAG) {
				analysisData(struct.getOthers(), false);
			} else {
				throw new IOException("BAD DATA:" + tmp);
			}

		} catch (IOException ex) {
			ex.printStackTrace();
		}

	}

	/* 解压数据 added by wyp 20100112 */
	private byte[] decompress(byte[] data) {
		int originalSize = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
		int compressedSize = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);

		Inflater decompresser = new Inflater();
		decompresser.setInput(data, 4, compressedSize);
		// 对byte[]进行解压，同时可以要解压的数据包中的某一段数据，就好像从zip中解压出某一个文件一样。

		byte[] result = new byte[originalSize];

		try {
			decompresser.inflate(result);
		} catch (DataFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			result = null;
		}
		decompresser.end();

		return result;
	}

	private void putData(int type, byte[] data) {
		String key = Integer.toString(type);
		if (hash.containsKey(key))// 处理key冲突
		{
			byte[] tempData = (byte[]) hash.get(key);
			data = mergeTwoByteArray(tempData, data);
		}
		if (null != data && data.length != 0) {
			hash.put(Integer.toString(type), data);
		}
	}

	private byte[] mergeTwoByteArray(byte[] arr1, byte[] arr2) {// 合并两个byte数组
		int arr1Length = (arr1 == null) ? 0 : arr1.length;
		int arr2Length = (arr2 == null) ? 0 : arr2.length;
		int totalLength = arr1Length + arr2Length;

		if (totalLength < 1)
			return null;

		byte[] temp = new byte[totalLength];
		if (arr1Length > 0)
			System.arraycopy(arr1, 0, temp, 0, arr1Length);
		if (arr2Length > 0)
			System.arraycopy(arr2, 0, temp, arr1Length, arr2Length);

		return temp;
	}

	public byte[] getData(int key) {
		return (byte[]) hash.get(Integer.toString(key));
	}
}
